package com.gitee.jastee.es;

import cn.hutool.core.codec.Base64Encoder;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import cn.hutool.log.Log;
import cn.hutool.log.LogFactory;
import cn.hutool.log.level.Level;
import com.gitee.jastee.util.ParameterTool;

/**
 * ES SQL查询
 *
 * @author Jast
 * @description
 * @date 2022-03-03 09:38
 */
public class ElasticSearchSQL {

    private static final Log log = LogFactory.get();

    private static ParameterTool parameterTool;

    /** 查询前缀 */
    private static String queryPrefix = "{\"query\": \"";
    /** 查询后缀 */
    private static String querySuffix = "\"}";

    private static String authorization = null;

    public static void main(String[] args) {
        log.isEnabled(Level.DEBUG);
        String query = query(args);
        System.out.println(query);
    }

    public static String query(String[] args) {

        // 传入参数
        // --es.address 10.16.0.33:9200 --es.sql "select * from ads_user_profile limit 1 "
        // --es.security true --es.authorization "Basic ZWxhc3RpYzpBdnJpczJAMjIjIQ==" --format true

        parameterTool = ParameterTool.fromArgs(args);

        String convert = convert();

        String sql = parameterTool.getRequired("es.sql");
        int fromIndex = sql.indexOf("from");
        String indexName = sql.substring(fromIndex + 4).trim();
        int indexOf = indexName.indexOf(" ");
        if (indexOf != -1) {
            indexName = indexName.substring(0, indexOf).trim();
        }

        log.debug("查询索引名称:{}", indexName);

        String queryUrl =
                "http://" + parameterTool.getRequired("es.address") + "/" + indexName + "/_search";
        log.debug("查询数据连接:{}", queryUrl);
        log.debug("查询数据参数:{}", convert);
        HttpRequest httpRequest = HttpUtil.createGet(queryUrl);
        if (StrUtil.isNotBlank(authorization)) {
            httpRequest.header("Authorization", authorization);
        }
        httpRequest.body(convert);
        String body = httpRequest.execute().body();
        if (parameterTool.getBoolean("format", false)) {
            return JSONUtil.parse(body).toStringPretty();
        }
        return body;
    }

    /**
     * @date 2022/03/3 上午10:52
     * @description 获取查询ES语句
     * @author Jast
     */
    private static String convert() {

        String translate = translate();

        log.debug("ElasticSearch SQL 转换结果:{}", translate);

        JSONObject jsonObject = JSONUtil.parseObj(translate);

        JSONObject query = jsonObject.getJSONObject("query");
        Integer size = jsonObject.getInt("size");

        JSONObject result = new JSONObject();

        result.set("size", size);
        result.set("query", query);

        return result.toString();
    }
    /**
     * @date 2022/03/3 上午10:43
     * @description 调用ES接口获取初步需要执行的DSL
     * @author Jast
     */
    private static String translate() {
        String esAddress = parameterTool.getRequired("es.address");
        String url = getUrl(esAddress);
        log.info("请求地址:{}", esAddress);
        String sql = parameterTool.getRequired("es.sql");
        String param = queryPrefix + sql + querySuffix;
        log.info("查询SQL:{}", sql);
        boolean security = parameterTool.getBoolean("es.security", false);

        HttpRequest request = HttpUtil.createPost(url);

        if (security) {
            log.info("已启用权限校验");
            String authorizationValue = parameterTool.get("es.authorization", null);
            if (StrUtil.isNotBlank(authorizationValue)) {
                authorization = authorizationValue;
            } else {
                String userName = parameterTool.getRequired("es.username");
                String password = parameterTool.getRequired("es.password");
                authorization = "Basic " + Base64Encoder.encode(userName + ":" + password);
            }
            request.header("Authorization", authorization);
        } else {
            log.info("未启用权限校验");
        }
        request.body(param);
        return request.execute().body();
    }

    private static String getUrl(String esAddress) {
        return "http://" + esAddress + "/_sql/translate";
    }
}
